﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Data;
using System.Collections.Specialized;
using System.Text.RegularExpressions;


namespace IIFProcessor
{
    class Processor
    {
        public const string dataLineString = "SPL";
        public const string defaultSearchText = "Select Income or Expense Item, then \"Process\"";
        private int targetColumn;
        private int matchFirst;
        public Processor()
        {
            targetColumn = IIFProcessor.Properties.Settings.Default.TargetColumn;
            matchFirst = IIFProcessor.Properties.Settings.Default.MatchNumberOfChars;
        }
        /// <summary>
        /// IIF File as DataTable
        /// </summary>
        public DataTable TableSource
        {
            get;
            private set;
        }

        /// <summary>
        /// Load data from IIF file
        /// </summary>
        /// <param name="filename">iif filename</param>
        public void LoadFile(string filename)
        {
            TableSource = new DataTable();
            TableSource.CaseSensitive = true;
            TextReader tReader = new StreamReader(filename);
            while (tReader.Peek() >= 0)
            {
                string iifLine = tReader.ReadLine();
                StoreLine(iifLine, string.Empty, string.Empty, string.Empty);
            }
            tReader.Close();
        }

        private void StoreLine(string iifLine, string searchText, string textMatch, string textReplacement)
        {
            string[] iifLineSeparated = iifLine.Split('\t');

            while (TableSource.Columns.Count < iifLineSeparated.Length)
            {
                TableSource.Columns.Add();
                if (TableSource.Columns.Count == iifLineSeparated.Length)
                {
                    DataColumn dcRec = new DataColumn("IsChanged", typeof(int));
                    dcRec.DefaultValue = 0;
                    TableSource.Columns.Add(dcRec);
                }

            }

            DataRow drIIFLine = TableSource.NewRow();
            for (int i = 0; i < iifLineSeparated.Length - 1; i++)
            {
                drIIFLine[i] = iifLineSeparated[i];

                if (i == 2 && !string.IsNullOrEmpty(searchText) && iifLineSeparated[i] == searchText)
                {
                    if (!string.IsNullOrEmpty(textMatch))
                    {
                        if (iifLineSeparated[i + 1].StartsWith(textMatch))
                        {
                            drIIFLine[i] = textReplacement;
                            drIIFLine[iifLineSeparated.Length] = true;
                        }
                    }
                    else
                    {
                        drIIFLine[i] = textReplacement;
                        drIIFLine[iifLineSeparated.Length] = true;
                    }
                }
            }
            TableSource.Rows.Add(drIIFLine);
        }
        /// <summary>
        /// Write data to new IIF file
        /// </summary>
        /// <param name="filename">iif filename</param>
        public string GetExportData(DataTable exportData)
        {
            StringBuilder sb = new StringBuilder();
            foreach (DataRow dr in exportData.Rows)
            {
                for (int i = 0; i < exportData.Columns.Count - 1; i++)
                {
                    if (dr[i] != System.DBNull.Value)
                    {
                        sb.Append(Convert.ToString(dr[i])).Append("\t");
                    }
                }
                if (sb.Length > 0)
                    sb.Remove(sb.Length - 1, 1);
                sb.Append(System.Environment.NewLine);
            }
            return sb.ToString();
        }

        public StringCollection GetAccountTypes()
        {
            string columnName = TableSource.Columns[targetColumn].ColumnName;
            DataTable accntTypes = TableSource.DefaultView.ToTable(true, TableSource.Columns[0].ColumnName, columnName);
            StringCollection result = new StringCollection();
            result.Add(defaultSearchText);
            foreach (DataRow dr in accntTypes.Rows)
            {
                if (Convert.ToString(dr[0]) == dataLineString)
                {
                    result.Add(Convert.ToString(dr[1]));
                }
            }
            return result;
        }

        public DataRow[] SearchMatches(string text)
        {
            DataRow[] matches = TableSource.Select(TableSource.Columns[0].ColumnName + " = '" + dataLineString + "' AND " + TableSource.Columns[targetColumn].ColumnName + " ='" + text + "'", "", DataViewRowState.Added | DataViewRowState.Unchanged);
            return matches;
        }
        public string InitializeStep(DataRow[] rows)
        {
            int silentFirstMatch = 0;
            return InitializeStep(rows, ref silentFirstMatch);
        }
        public string InitializeStep(DataRow[] rows, ref int firstMatch)
        {
            foreach (DataRow dr in rows)
            {
                string targetRow = Convert.ToString(dr[targetColumn]);
                string firstCol = Convert.ToString(dr[0]);
                if (dr.RowState != DataRowState.Modified)
                {
                    string foundMatch = Convert.ToString(dr[targetColumn + 1]);
                    foundMatch = foundMatch.Replace("\"", "");
                    foundMatch = foundMatch.Substring(0, Math.Min(foundMatch.Length, matchFirst));
                    DataRow[] matches = SelectMatchRows(targetRow, foundMatch);
                    foreach (DataRow drMatch in matches)
                    {
                        drMatch.AcceptChanges();
                    }
                    if (matches.Length > 0)
                        firstMatch = TableSource.Rows.IndexOf(matches[0]);
                    else
                        firstMatch = TableSource.Rows.Count - 1;
                    return foundMatch;
                }
            }
            firstMatch = TableSource.Rows.Count - 1;
            return string.Empty;
        }
        public int ReplaceStep(string text, string match, string replaceText)
        {
            string replacementText = "\"" + replaceText + "\"";
            DataRow[] matches = SelectMatchRows(text, match);
            foreach (DataRow dr in matches)
            {
                dr[targetColumn] = replacementText;
                dr.AcceptChanges();
                dr.SetModified();
            }
            return matches.Length;
        }
        /// <summary>
        /// Gets true if the current file loaded has changes
        /// </summary>
        public bool HasChanges
        {
            get
            {
                return TableSource.GetChanges(DataRowState.Modified | DataRowState.Unchanged) != null;
            }
        }
        public DataRow[] SelectMatchRows(string text, string match)
        {
            match = match.Replace("*", "[*]");
            match = match.Replace("%", "[%]");
            match = match.Replace("'", "''");

            DataRow[] matches = TableSource.Select(TableSource.Columns[0].ColumnName + " = '" + dataLineString + "' AND " + TableSource.Columns[targetColumn].ColumnName + " ='" + text + "' AND (" + TableSource.Columns[targetColumn + 1].ColumnName + " LIKE '" + match + "%' OR " + TableSource.Columns[targetColumn + 1].ColumnName + " LIKE '\"" + match + "%')", "", DataViewRowState.Added | DataViewRowState.Unchanged);

            return matches;
        }

        public void CovertFileToTable(string paypalData)
        {
            TableSource = new DataTable("ProcessorDate");
            TableSource.CaseSensitive = true;
            string[] lines = Regex.Split(paypalData, "\r\n");

            foreach (string line in lines)
            {
                StoreLine(line, string.Empty, string.Empty, string.Empty);
            }
        }

        public void ProcessData(string paypalData, string searchText, string textMatch, string textReplacement)
        {
            TableSource = new DataTable("ProcessorDate");
            TableSource.CaseSensitive = true;
            string[] lines = Regex.Split(paypalData, "\r\n");

            foreach (string line in lines)
            {
                StoreLine(line, searchText, textMatch, textReplacement);
            }
        }


        public DataTable ReplaceData(DataTable paypalData, string searchText, string textMatch, string textReplacement, bool IsStepBy)
        {
            bool isFound = false;
            int searchCol = 2;
            foreach (DataRow row in paypalData.Rows)
            {

                if (searchText == row[searchCol].ToString())
                {
                    if (string.IsNullOrEmpty(textMatch))
                    {
                        row[searchCol] = textReplacement;
                        isFound = true;
                    }
                    else
                    {
                        if (row[searchCol + 1].ToString().StartsWith(textMatch))
                        {
                            row[searchCol] = textReplacement;
                            isFound = true;
                        }
                    }
                    if (isFound)
                    {
                        row["IsChanged"] = (int)row["IsChanged"] + 1;
                        if (IsStepBy)
                            return paypalData;
                        isFound = false;
                    }

                }
            }
            return paypalData;
        }

    }
}
